home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume3 / sps / part2 < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  46.7 KB

  1. From: seismo!mcvax!cernvax!hslrswi!robert (Robert Ward)
  2. Subject: SPS (Show Process Status) Part 2 of 2
  3. Newsgroups: mod.sources
  4. Approved: jpn@panda.UUCP
  5.  
  6. Mod.sources:  Volume 3, Issue 56
  7. Submitted by: seismo!mcvax!cernvax!hslrswi!robert (Robert Ward)
  8.  
  9.  
  10. #! /bin/sh
  11. # This is a shell archive, meaning:
  12. # 1. Remove everything above the #! /bin/sh line.
  13. # 2. Save the resulting text in a file.
  14. # 3. Execute the file with /bin/sh (not csh) to create the files:
  15. #    main.c
  16. #    mktree.c
  17. #    needed.c
  18. #    openfiles.c
  19. #    percentmem.c
  20. #    prcmd.c
  21. #    prcpu.c
  22. #    prheader.c
  23. #    printall.c
  24. #    printproc.c
  25. #    prsummary.c
  26. #    readstatus.c
  27. #    selectproc.c
  28. #    selecttty.c
  29. #    sps.h
  30. #    termwidth.c
  31. #    ttystatus.c
  32. #    waitingfor.c
  33. # This archive created: Mon Dec  2 18:41:14 1985
  34. export PATH; PATH=/bin:$PATH
  35. echo shar: extracting "'main.c'" '(2626 characters)'
  36. if test -f 'main.c'
  37. then
  38.     echo shar: will not over-write existing file "'main.c'"
  39. else
  40. sed 's/^X//' << \SHAR_EOF > 'main.c'
  41. # include       "sps.h"
  42. # include       "flags.h"
  43. # include       <h/text.h>
  44. # include       <stdio.h>
  45.  
  46. /* SPS - Show Process Status */
  47. /* J. R. Ward - Hasler AG Bern - 24 May 1985 */
  48. main ( argc,argv )
  49.  
  50. int                             argc ;
  51. char                            **argv ;
  52.  
  53. {
  54.     register struct process *plist ;
  55.     register struct process *process ;
  56.     register struct text    *text ;
  57.     int                     flinfo ;
  58.     extern struct flags     Flg ;
  59.     extern struct info      Info ;
  60.     extern int              Flmem ;
  61.     extern int              Flkmem ;
  62.     extern int              Flswap ;
  63.     char                    *getcore() ;
  64.     struct process          *needed(), *mktree() ;
  65.  
  66.     /* Renice as fast as possible for root (Suggested by Gregorio!mogul) */
  67.     if ( !getuid() )
  68.         (void)nice( -40 ) ;
  69.     /* Decode the flag arguments */
  70.     flagdecode( argc, argv ) ;      
  71.     /* Determine the terminal width */
  72.     if ( !Flg.flg_w && !Flg.flg_N && !Flg.flg_i )
  73.         termwidth() ;
  74.     /* Open the cpu physical memory, kernel virtual memory and swap device*/
  75.     if ( Flg.flg_k )
  76.     {
  77.         Flmem = openfile( Flg.flg_k ) ;
  78.         Flkmem = Flmem ;
  79.     }
  80.     else
  81.     {
  82.         Flmem = openfile( FILE_MEM ) ;
  83.         Flkmem = openfile( FILE_KMEM ) ;
  84.         if ( !Flg.flg_o )
  85.             Flswap = openfile( FILE_SWAP ) ;
  86.     }
  87.     if ( Flg.flg_i )
  88.     {       /* -i flag for info file initialisation */
  89.         initialise() ;          
  90.         exit( 0 ) ;
  91.     }
  92.     /* Read the information file */
  93.     flinfo = openfile( Flg.flg_j ? Flg.flg_j : FILE_INFO ) ;
  94.     if ( read( flinfo, (char*)&Info, sizeof( struct info ) )
  95.     != sizeof( struct info ) )
  96.     {
  97.         fprintf( stderr, "sps - Can't read info file %s",
  98.             Flg.flg_j ? Flg.flg_j : FILE_INFO ) ;
  99.         sysperror() ;
  100.     }
  101.     (void)close( flinfo ) ;
  102.     /* Find current tty status */
  103.     ttystatus() ;                   
  104.     /* Now that we know the available ttys, decode the flags */
  105.     flagsetup() ;                   
  106.     process = (struct process*)getcore(Info.i_nproc*sizeof(struct process));
  107.     text = (struct text*)getcore( Info.i_ntext * sizeof( struct text ) ) ;
  108.     do
  109.     {       /* Read current process and text status */
  110.         readstatus( process, text ) ;
  111.         /* Select those processes to be listed */
  112.         plist = needed( process, text ) ;
  113.         /* Form a tree of listed processes */
  114.         plist = mktree( process, plist ) ;
  115.         if ( !Flg.flg_N )
  116.         {       /* Print the processes */
  117.             prheader() ;
  118.             printall( plist, 0 ) ;
  119.         }
  120.         prsummary() ;
  121.         (void)fflush( stdout ) ;
  122.         if ( Flg.flg_r )        
  123.         {       /* If repeating, again get tty status */
  124.             ttystatus() ;
  125.             if ( Flg.flg_rdelay )
  126. # ifdef BSD42
  127.                 sleep( Flg.flg_rdelay ) ;
  128. # else
  129.                 sleep( (int)Flg.flg_rdelay ) ;
  130. # endif
  131.         }
  132.     } while ( Flg.flg_r ) ;
  133.     exit( 0 ) ;
  134. }
  135. SHAR_EOF
  136. if test 2626 -ne "`wc -c < 'main.c'`"
  137. then
  138.     echo shar: error transmitting "'main.c'" '(should have been 2626 characters)'
  139. fi
  140. fi # end of overwriting check
  141. echo shar: extracting "'mktree.c'" '(1626 characters)'
  142. if test -f 'mktree.c'
  143. then
  144.     echo shar: will not over-write existing file "'mktree.c'"
  145. else
  146. sed 's/^X//' << \SHAR_EOF > 'mktree.c'
  147. # include       "sps.h"
  148.  
  149. /*
  150. ** MKTREE - Sort the needed processes by subtree and at the top by user.
  151. ** This procedure takes a list of processes (as returned by needed())
  152. ** and returnes a pointer to a sorted list.
  153. */
  154. struct process  *mktree ( process, plist )
  155.  
  156. struct process                  *process ;
  157. struct process                  *plist ;
  158.  
  159. {
  160.     register struct process *p ;
  161.     register struct process *pp ;
  162.     register struct process *lp ;
  163.     struct process          *op ;
  164.     struct process          proot ;
  165.  
  166.     proot.pr_sibling = (struct process*)0 ;
  167.     for ( p = plist ; p ; p = p->pr_plink )
  168.     {
  169.         if ( p->pr_pptr > &process[1] )
  170.         {
  171.             for ( pp = plist ; pp ; pp = pp->pr_plink )
  172.             {
  173.                 if ( pp != p->pr_pptr )
  174.                     continue ;
  175.                 if ( lp = pp->pr_child )
  176.                 {       /* Does process have children ? */
  177.                     op = (struct process*)0 ;
  178.                     while (lp &&
  179.                     lp->pr_p.p_pid < p->pr_p.p_pid )
  180.                     {
  181.                         op = lp ;
  182.                         lp=lp->pr_sibling ;
  183.                     }
  184.                     if ( op )
  185.                     {
  186.                         p->pr_sibling = lp ;
  187.                         op->pr_sibling = p ;
  188.                         break ;
  189.                     }
  190.                 }       
  191.                 p->pr_sibling = lp ;
  192.                 pp->pr_child = p ;
  193.                 break ;
  194.             }
  195.             if ( pp )
  196.                 continue ;
  197.         }
  198.         /* We have a top level process, sort into top level list.
  199.            The top level is sorted firstly by user-id and then
  200.            by process-id. */
  201.         lp = &proot ;
  202.         pp = lp->pr_sibling ;
  203.         while ( pp )
  204.         {
  205.             if ( p->pr_p.p_uid < pp->pr_p.p_uid )
  206.                 break ;
  207.             if ( p->pr_p.p_uid == pp->pr_p.p_uid
  208.             && p->pr_p.p_pid < pp->pr_p.p_pid )
  209.                 break ;
  210.             lp = pp, pp = pp->pr_sibling ;
  211.         }
  212.         p->pr_sibling = lp->pr_sibling ;
  213.         lp->pr_sibling = p ;
  214.     }
  215.     return ( proot.pr_sibling ) ;
  216. }
  217. SHAR_EOF
  218. if test 1626 -ne "`wc -c < 'mktree.c'`"
  219. then
  220.     echo shar: error transmitting "'mktree.c'" '(should have been 1626 characters)'
  221. fi
  222. fi # end of overwriting check
  223. echo shar: extracting "'needed.c'" '(4455 characters)'
  224. if test -f 'needed.c'
  225. then
  226.     echo shar: will not over-write existing file "'needed.c'"
  227. else
  228. sed 's/^X//' << \SHAR_EOF > 'needed.c'
  229. # include       "sps.h"
  230. # include       "flags.h"
  231. # include       <h/text.h>
  232. # include       <stdio.h>
  233.  
  234. /*
  235. ** NEEDED - Determine which processes are needed for the printout
  236. ** and add these to a list of needed processes.
  237. */
  238. struct process  *needed ( process, text )
  239.  
  240. register struct process         *process ;
  241. struct text                     *text ;
  242.  
  243. {
  244.     register struct process *p ;
  245.     register struct process *plist ;
  246.     struct process          *lastp ;
  247.     int                     uid ;
  248.     extern struct flags     Flg ;
  249.     extern union userstate  User ;
  250.     extern struct info      Info ;
  251.     extern struct ttyline   Notty ;
  252.     struct ttyline          *findtty() ;
  253.     char                    *getcmd() ;
  254.  
  255.     plist = (struct process*)0 ;
  256.     lastp = &process[ Info.i_nproc ] ;
  257.     /* Normalise internal pointers from kernel addresses. For each kmem
  258.        address in the `proc' and `text' structures, we convert that
  259.        address for our own internal use. */
  260.     for ( p = process ; p < lastp ; p++ )
  261.     {                               
  262.         if ( !p->pr_p.p_stat )  
  263.             continue ;
  264.         /* Normalise internal text pointers */
  265.         if ( p->pr_p.p_textp )
  266.             p->pr_p.p_textp = &text[p->pr_p.p_textp - Info.i_text0];
  267.         /* Normalise internal linked list of processes */
  268.         p->pr_plink = p->pr_p.p_link ?
  269.             &process[ p->pr_p.p_link  - Info.i_proc0 ] :
  270.             (struct process*)0 ;
  271.         /* Normalise internal parent pointers */
  272.         p->pr_pptr = p->pr_p.p_pptr ?
  273.             &process[ p->pr_p.p_pptr - Info.i_proc0 ] :
  274.             (struct process*)0 ;
  275.         /* Check for valid parent pointers */
  276.         if ( !p->pr_pptr )
  277.         {
  278.             p->pr_pptr = process ;
  279.             continue ;
  280.         }
  281.         if ( p->pr_pptr < process || p->pr_pptr >= lastp )
  282.         {
  283.             fprintf( stderr, "sps - process %d has bad pptr\n",
  284.                 p->pr_p.p_pid ) ;
  285.             p->pr_pptr = process ;
  286.         }
  287.     }
  288.     /* For each process, see if it is a candidate for selection.
  289.        If so, retrieve its command arguments and upage information. */
  290.     uid = getuid() ;
  291.     for ( p = process ; p < lastp ; p++ )
  292.     {                               
  293.         if ( !p->pr_p.p_stat )
  294.             continue ;
  295.         /* Count processes and sizes */
  296.         summarise( p ) ;
  297.         /* Select the given processes. Bear in mind that selection
  298.            of processes based on the `F' and `T' flags must be
  299.            postponed until the upage is accessed. */
  300.         if ( !Flg.flg_F && !Flg.flg_T && !selectproc( p, process, uid ))
  301.             continue ;
  302.         /* Try to find the process' command arguments. Accessing the
  303.            arguments also involves retrieving the upage. */
  304.         p->pr_cmd = getcmd( p ) ;
  305.         /* If the upage was found successfully, use this information */
  306.         if ( p->pr_upag )       
  307.         {
  308. # ifdef BSD42
  309.             p->pr_rself = User.u_us.u_ru ;
  310.             p->pr_rchild = User.u_us.u_cru ;
  311. # else
  312.             p->pr_vself = User.u_us.u_vm ;
  313.             p->pr_vchild = User.u_us.u_cvm ;
  314. # endif
  315.             p->pr_tty = findtty( p ) ;
  316.             p->pr_files = filecount() ;
  317.         }
  318.         else
  319.             p->pr_tty = &Notty ;
  320.         /* Select on the basis of the `F' and `T' flags */
  321.         if ( Flg.flg_F          
  322.         && !(p->pr_p.p_pgrp && p->pr_p.p_pgrp == p->pr_tty->l_pgrp) )
  323.             continue ;
  324.         if ( Flg.flg_T && !selecttty( p ) )
  325.             continue ;
  326.         /* Arrive here with a selected process. Add this to the
  327.            linked list of needed processes. */
  328.         p->pr_plink = plist ;   
  329.         plist = p ;
  330.         p->pr_child = (struct process*)0 ;
  331.         p->pr_sibling = (struct process*)0 ;
  332.     }
  333.     return ( plist ) ;
  334. }
  335.  
  336. /* SUMMARISE - Summarises the given process into the `Summary' structure */
  337. /*
  338. ** SHOULD ACCOUNT HERE FOR THE SIZE OF LOADED PAGE TABLES, BUT WE DON'T REALLY
  339. ** KNOW THEIR RESIDENT SIZES.
  340. */
  341. summarise ( p )
  342.  
  343. register struct process         *p ;
  344.  
  345. {
  346.     register struct text    *tp ;
  347.     int                     busy ;
  348.     extern struct summary   Summary ;
  349.  
  350.     Summary.sm_ntotal++ ;
  351.     if ( p->pr_p.p_stat == SZOMB )
  352.         return ;
  353.     /* Firstly, account for processes */
  354.     Summary.sm_ktotal += p->pr_p.p_dsize + p->pr_p.p_ssize ;
  355.     Summary.sm_kloaded += p->pr_p.p_rssize ;
  356.     Summary.sm_kswapped += p->pr_p.p_swrss ;
  357.     if ( p->pr_p.p_flag & SLOAD )
  358.         Summary.sm_nloaded++ ;
  359.     else
  360.         Summary.sm_nswapped++ ;
  361.     busy = (p->pr_p.p_stat == SRUN) || (p->pr_p.p_stat==SSLEEP
  362.          && (p->pr_p.p_pri<PZERO && p->pr_p.p_pid > MSPID) ) ;
  363.     if ( busy )
  364.     {
  365.         Summary.sm_nbusy++ ;
  366.         Summary.sm_kbusy += p->pr_p.p_dsize + p->pr_p.p_ssize ;
  367.     }
  368.     /* Now account for their texts */
  369.     if ( !(tp = p->pr_p.p_textp) || !tp->x_count )
  370.         return ;                
  371.     Summary.sm_ktotal += tp->x_size ;
  372.     Summary.sm_kloaded += tp->x_rssize ;
  373.     Summary.sm_kswapped += tp->x_swrss ;
  374.     if ( busy )
  375.         Summary.sm_kbusy += tp->x_size ;
  376.     tp->x_count = 0 ;
  377. }
  378. SHAR_EOF
  379. if test 4455 -ne "`wc -c < 'needed.c'`"
  380. then
  381.     echo shar: error transmitting "'needed.c'" '(should have been 4455 characters)'
  382. fi
  383. fi # end of overwriting check
  384. echo shar: extracting "'openfiles.c'" '(2626 characters)'
  385. if test -f 'openfiles.c'
  386. then
  387.     echo shar: will not over-write existing file "'openfiles.c'"
  388. else
  389. sed 's/^X//' << \SHAR_EOF > 'openfiles.c'
  390. # include       <stdio.h>
  391. # include       "sps.h"
  392. # include       "flags.h"
  393.  
  394. /* Miscellaneous procedures */
  395.  
  396. /* OPENFILE - Opens the named file */
  397. openfile ( name )
  398.  
  399. char                            *name ;
  400.  
  401. {
  402.     register int            fd ;
  403.  
  404.     if ( (fd = open( name, 0 )) >= 0 )
  405.         return ( fd ) ;
  406.     fprintf( stderr, "sps - Can't open %s", name ) ;
  407.     sysperror() ;
  408.     /* NOTREACHED */
  409. }
  410.  
  411. /* MEMSEEK - Seek on a special file */
  412. memseek ( fd, pos )
  413.  
  414. int                             fd ;
  415. long                            pos ;
  416.  
  417. {
  418.     extern int              errno ;
  419.     extern struct flags     Flg ;
  420.     long                    lseek() ;
  421.  
  422.     errno = 0 ;
  423.     if ( Flg.flg_k )
  424.         pos &= 0x7fffffff ;
  425.     (void)lseek( fd, pos, 0 ) ;
  426.     if ( errno )
  427.     {
  428.         fprintf( stderr, "sps - Seek failed" ) ;
  429.         sysperror() ;
  430.     }
  431. }
  432.  
  433. /* SWSEEK - Seek on the swap device */
  434. swseek ( pos )
  435.  
  436. long                            pos ;
  437.  
  438. {
  439.     extern int              Flswap ;
  440.     extern int              errno ;
  441.     long                    lseek() ;
  442.  
  443.     errno = 0 ;
  444.     (void)lseek( Flswap, pos, 0 ) ;
  445.     if ( errno )
  446.     {
  447.         fprintf( stderr, "sps - Seek failed" ) ;
  448.         sysperror() ;
  449.     }
  450. }
  451.  
  452. # ifdef lint
  453. int                             errno ;
  454. int                             sys_nerr ;
  455. char                            *sys_errlist[] ;
  456. # endif
  457.  
  458. /* SYSPERROR - Reports a system defined error msg and then exits gracefully */
  459. sysperror ()
  460. {
  461.     extern int              errno ;
  462.     extern int              sys_nerr ;
  463.     extern char             *sys_errlist[] ;
  464.  
  465.     if ( 0 < errno && errno < sys_nerr )
  466.         fprintf( stderr, " : %s", sys_errlist[errno] ) ;
  467.     (void)fputc( '\n', stderr ) ;
  468.     exit( 1 ) ;
  469. }
  470.  
  471. /* STRSAVE - Store a string in core for later use. */
  472. char    *strsave ( cp )
  473.  
  474. register char                   *cp ;
  475.  
  476. {
  477.     register char           *chp ;
  478.     char                    *getcore(), *strcpy() ;
  479.  
  480.     chp = getcore( strlen( cp ) + 1 ) ;
  481.     (void)strcpy( chp, cp ) ;
  482.     return ( chp ) ;
  483. }
  484.  
  485. /* GETCORE - Allocate and return a pointer to the asked for amount of core */
  486. char    *getcore ( size )
  487.  
  488. register int                    size ;
  489.  
  490. {
  491.     register char           *chp ;
  492.     char                    *malloc() ;
  493.  
  494.     if ( chp = malloc( (unsigned)size ) )
  495.         return ( chp ) ;
  496.     fprintf( stderr, "sps - Out of core" ) ;
  497.     sysperror() ;
  498.     /* NOTREACHED */
  499. }
  500.  
  501. union flaglist  *getflgsp ( argc )
  502.  
  503. register int                    argc ;
  504.  
  505. {
  506.     char                    *getcore() ;
  507.  
  508.     return ( (union flaglist*)getcore( sizeof( union flaglist )*argc ) ) ;
  509. }
  510.  
  511. /* PREXIT - Print an error message and exit */
  512. /* VARARGS1 */
  513. /* ARGSUSED */
  514. prexit ( fmt, args )
  515.  
  516. char                            *fmt ;
  517.  
  518. {
  519.     _doprnt( fmt, &args, stderr ) ;
  520.     exit( 1 ) ;
  521. }
  522. SHAR_EOF
  523. if test 2626 -ne "`wc -c < 'openfiles.c'`"
  524. then
  525.     echo shar: error transmitting "'openfiles.c'" '(should have been 2626 characters)'
  526. fi
  527. fi # end of overwriting check
  528. echo shar: extracting "'percentmem.c'" '(823 characters)'
  529. if test -f 'percentmem.c'
  530. then
  531.     echo shar: will not over-write existing file "'percentmem.c'"
  532. else
  533. sed 's/^X//' << \SHAR_EOF > 'percentmem.c'
  534. # include       "sps.h"
  535. # include       <h/text.h>
  536. # ifdef BSD42
  537. # include    <machine/pte.h>
  538. # else
  539. # include       <h/pte.h>
  540. # include       <h/vmparam.h>
  541. # endif
  542. # include       <h/vmmac.h>
  543.  
  544. /* PERCENTMEM - Returns the percentage of real memory used by this process */
  545. double  percentmem ( p )
  546.  
  547. register struct process         *p ;
  548.  
  549. {
  550.     register struct text    *tp ;
  551.     int                     szptudot ;
  552.     double                  fracmem ;
  553.     extern struct info      Info ;
  554.  
  555.     tp = p->pr_p.p_textp ;
  556.     if ( !(p->pr_p.p_flag & SLOAD) || !tp )
  557.         return ( 0.0 ) ;
  558.     szptudot = UPAGES + clrnd( ctopt( p->pr_p.p_dsize + p->pr_p.p_ssize ) );
  559.     fracmem = ( (double)p->pr_p.p_rssize + szptudot ) / CLSIZE ;
  560.     if ( tp->x_ccount )
  561.         fracmem += ((double)tp->x_rssize)/CLSIZE/tp->x_ccount ;
  562.     return ( 100.0 * fracmem / (double)Info.i_ecmx ) ;
  563. }
  564. SHAR_EOF
  565. if test 823 -ne "`wc -c < 'percentmem.c'`"
  566. then
  567.     echo shar: error transmitting "'percentmem.c'" '(should have been 823 characters)'
  568. fi
  569. fi # end of overwriting check
  570. echo shar: extracting "'prcmd.c'" '(709 characters)'
  571. if test -f 'prcmd.c'
  572. then
  573.     echo shar: will not over-write existing file "'prcmd.c'"
  574. else
  575. sed 's/^X//' << \SHAR_EOF > 'prcmd.c'
  576. # include       "sps.h"
  577. # include       "flags.h"
  578.  
  579. /* PRCMD - Prints the command arguments according to the switches */
  580. prcmd ( p, lpad, width )
  581.  
  582. register struct process         *p ;
  583. int                             lpad ;
  584. int                             width ;
  585.  
  586. {
  587.     extern struct flags     Flg ;
  588.     extern unsigned         Termwidth ;
  589.  
  590.     printf( "%*d ", lpad, p->pr_p.p_pid ) ;
  591.     if ( Flg.flg_f )
  592.     {
  593.         printf( "%5d ", p->pr_p.p_ppid ) ;
  594.         width -= 6 ;
  595.     }
  596.     if ( Flg.flg_g )
  597.     {
  598.         printf( "%5d ", p->pr_p.p_pgrp ) ;
  599.         width -= 6 ;
  600.     }
  601.     width += Termwidth ;
  602.     if ( Flg.flg_w )
  603.         printf( "%s\n", p->pr_cmd ) ;
  604.     else if ( width > 0 )
  605.         printf( "%-.*s\n", width, p->pr_cmd ) ;
  606.     if ( p->pr_csaved )
  607.         free( p->pr_cmd ) ;
  608. }
  609. SHAR_EOF
  610. if test 709 -ne "`wc -c < 'prcmd.c'`"
  611. then
  612.     echo shar: error transmitting "'prcmd.c'" '(should have been 709 characters)'
  613. fi
  614. fi # end of overwriting check
  615. echo shar: extracting "'prcpu.c'" '(1538 characters)'
  616. if test -f 'prcpu.c'
  617. then
  618.     echo shar: will not over-write existing file "'prcpu.c'"
  619. else
  620. sed 's/^X//' << \SHAR_EOF > 'prcpu.c'
  621. # include       "sps.h"
  622.  
  623. # ifdef BSD42
  624.  
  625. /* PRCPU - Print cpu time */
  626. prcpu ( time, utime )
  627.  
  628. register time_t                 time ;
  629. time_t                          utime ;
  630.  
  631. {
  632.     time += utime / 1000000 ;
  633.     utime %= 1000000 ;
  634.     if ( time < 0L )
  635.     {       /* Ignore negative times */
  636.         printf( "     " ) ;     
  637.         return ;
  638.     }
  639.     if ( time < 60L*10L )
  640.     {       /* Print as seconds if less than 1000 seconds */
  641.         printf( "%3d.%1d", (int)time, (int)utime/100000 ) ;
  642.         return ;
  643.     }
  644.     /* Print as minutes if less than 10 hours ; print as hours if less than
  645.        10 days, else print as days. */
  646.     if ( time < 60L*60L*10L )               
  647.         printf( "%3D M", time/60L ) ;
  648.     else if ( time < 24L*60L*60L*10L )
  649.         printf( "%3D H", time/60L/60L ) ;
  650.     else
  651.         printf( "%3D D", time/60L/60L/24L ) ;
  652. }
  653.  
  654. # else
  655.  
  656. /* PRCPU - Print cpu time */
  657. prcpu ( time )
  658.  
  659. register time_t                 time ;
  660.  
  661. {
  662.     extern struct info      Info ;
  663.  
  664.     if ( time < 0L )
  665.     {       /* Ignore negative times */
  666.         printf( "     " ) ;     
  667.         return ;
  668.     }
  669.     if ( time < Info.i_hz*60L*10L )
  670.     {       /* Less than 10 minutes */
  671.         printf( "%3D.%1D", time/Info.i_hz,
  672.             (time % Info.i_hz / (Info.i_hz/10L)) ) ;
  673.         return ;
  674.     }
  675.     /* If less than 10 hours, print as minutes */
  676.     time /= Info.i_hz ;
  677.     /* Print as minutes if less than 10 hours ; print as hours if less than
  678.        10 days, else print as days. */
  679.     if ( time < 60L*60L*10L )               
  680.         printf( "%3D M", time/60L ) ;
  681.     else if ( time < 24L*60L*60L*10L )
  682.         printf( "%3D H", time/60L/60L ) ;
  683.     else
  684.         printf( "%3D D", time/60L/60L/24L ) ;
  685. }
  686.  
  687. # endif
  688. SHAR_EOF
  689. if test 1538 -ne "`wc -c < 'prcpu.c'`"
  690. then
  691.     echo shar: error transmitting "'prcpu.c'" '(should have been 1538 characters)'
  692. fi
  693. fi # end of overwriting check
  694. echo shar: extracting "'prheader.c'" '(438 characters)'
  695. if test -f 'prheader.c'
  696. then
  697.     echo shar: will not over-write existing file "'prheader.c'"
  698. else
  699. sed 's/^X//' << \SHAR_EOF > 'prheader.c'
  700. # include       "sps.h"
  701. # include       "flags.h"
  702.  
  703. /* PRHEADER - Print a header according to the switches */
  704. prheader ()
  705. {
  706.     extern struct flags     Flg ;
  707.  
  708.     printf( "Ty User    %s Proc#", Flg.flg_v ?
  709.         " Status Fl Nice Virtual Resident %M  Time Child %C" :
  710.         Flg.flg_d ?
  711.         "  Files    PageFaults Swap BlockI/O Kbytsecs" : "" ) ;
  712.     if ( Flg.flg_f )
  713.         printf( " Ppid#" ) ;
  714.     if ( Flg.flg_g )
  715.         printf( " Pgrp#" ) ;
  716.     printf( " Command\n" ) ;
  717. }
  718. SHAR_EOF
  719. if test 438 -ne "`wc -c < 'prheader.c'`"
  720. then
  721.     echo shar: error transmitting "'prheader.c'" '(should have been 438 characters)'
  722. fi
  723. fi # end of overwriting check
  724. echo shar: extracting "'printall.c'" '(430 characters)'
  725. if test -f 'printall.c'
  726. then
  727.     echo shar: will not over-write existing file "'printall.c'"
  728. else
  729. sed 's/^X//' << \SHAR_EOF > 'printall.c'
  730. # include       <stdio.h>
  731. # include       "sps.h"
  732.  
  733. /* PRINTALL - Recursively print the process tree. */
  734. printall ( p, md )
  735.  
  736. register struct process         *p ;
  737. register int                    md ;
  738.  
  739. {
  740.     while ( p )
  741.     {       /* Print this process */
  742.         printproc( p, md ) ;    
  743.         (void)fflush( stdout ) ;
  744.         /* Print child processes */
  745.         printall( p->pr_child, md+1 ) ;
  746.         /* Print brother processes */
  747.         p = p->pr_sibling ;     
  748.     }
  749. }
  750. SHAR_EOF
  751. if test 430 -ne "`wc -c < 'printall.c'`"
  752. then
  753.     echo shar: error transmitting "'printall.c'" '(should have been 430 characters)'
  754. fi
  755. fi # end of overwriting check
  756. echo shar: extracting "'printproc.c'" '(5844 characters)'
  757. if test -f 'printproc.c'
  758. then
  759.     echo shar: will not over-write existing file "'printproc.c'"
  760. else
  761. sed 's/^X//' << \SHAR_EOF > 'printproc.c'
  762. # include       "sps.h"
  763. # include       "flags.h"
  764. # include       <h/text.h>
  765.  
  766. /* PRINTPROC - Pretty print a process according to the switches. */
  767. printproc ( p, md )
  768.  
  769. register struct process         *p ;            
  770. int                             md ;            
  771.  
  772. {
  773.     register char           *chp ;
  774.     register struct text    *tp ;
  775.     register struct hashtab *hp ;
  776.     char                    chbuf[10] ;
  777.     time_t                  time ;
  778.     time_t                  chtime ;
  779. # ifdef BSD42
  780.     time_t                  utime ;
  781.     time_t                  uchtime ;
  782. # endif
  783.     extern short            Lastuid, Lastpgrp ;
  784.     extern struct flags     Flg ;
  785.     char                    *waitingfor() ;
  786.     struct hashtab          *hashuid() ;
  787.     double                  percentmem() ;
  788.  
  789.     /* List tty name and foreground/background/detached information */
  790.     printf( "%2.2s%c", p->pr_tty->l_name,
  791.         !p->pr_p.p_pgrp ? ' ' :
  792. # ifdef SDETACH
  793.         p->pr_p.p_flag & SDETACH ? '_' :
  794. # endif
  795.         p->pr_p.p_pgrp == p->pr_tty->l_pgrp ? '.' : ' ' ) ;
  796.     hp = hashuid( p->pr_p.p_uid ) ;
  797.     if ( !md  )                             
  798.     {       /* If a top-level process, list the user name */
  799.         if ( hp )
  800.             printf( "%-8.8s ", hp->h_uname ) ;
  801.         else
  802.             printf( "user%-4.4d ", p->pr_p.p_uid ) ;
  803.     }
  804.     else                                    
  805.     {       /* Usually list an asterisk for a child process */
  806.         md = md > 8 ? 8 : md ;
  807.         printf( "%*s%c", md, "",
  808.             p->pr_p.p_pgrp == Lastpgrp ? '|' : '*' ) ;      
  809.         /* But beware of setuid processes */
  810.         md = 8 - md ;
  811.         if ( p->pr_p.p_uid == Lastuid )
  812.             printf( "%-*.*s", md, md, "" ) ;
  813.         else if ( hp )
  814.             printf( "%-*.*s", md, md, hp->h_uname ) ;
  815.         else
  816.         {
  817.             md -= 4 ;
  818.             printf( "user%-*.*d", md, md, p->pr_p.p_uid ) ;
  819.         }
  820.     }
  821.     Lastuid = p->pr_p.p_uid ;
  822.     Lastpgrp = p->pr_p.p_pgrp ;
  823.     if ( Flg.flg_d )                        
  824.     {       /* List disc I/O and paging information */
  825.         if ( !p->pr_upag || p->pr_p.p_stat == SZOMB )
  826.         {
  827.             prcmd( p, 49, -63 ) ;
  828.             return ;
  829.         }
  830.         printf( "%2d %8d+%8d %4d %8d %8D ",
  831.             p->pr_files,
  832. # ifdef BSD42
  833.             p->pr_rself.ru_majflt,
  834.             p->pr_rself.ru_minflt,
  835.             p->pr_rself.ru_nswap,
  836.             p->pr_rself.ru_inblock + p->pr_rself.ru_oublock,
  837.             KBYTES( p->pr_rself.ru_idrss + p->pr_rself.ru_isrss
  838.                 + p->pr_rself.ru_ixrss ) ) ;
  839. # else
  840.             p->pr_vself.vm_majflt,
  841.             p->pr_vself.vm_minflt,
  842.             p->pr_vself.vm_nswap,
  843.             p->pr_vself.vm_inblk + p->pr_vself.vm_oublk,
  844.             KBYTES( (p->pr_vself.vm_idsrss
  845.                 + p->pr_vself.vm_ixrss) / Info.i_hz ) ) ;
  846. # endif
  847.         prcmd( p, 5, -63 ) ;
  848.         return ;
  849.     }
  850.     if ( !Flg.flg_v )                       
  851.     {       /* Not verbose so just list command arguments */
  852.         prcmd( p, 5, -19 ) ;
  853.         return ;
  854.     }
  855.     /* Arrive here if being verbose ; list cpu information */
  856.     switch ( p->pr_p.p_stat )               
  857.     {                                       
  858.         case SSLEEP :
  859.         case SWAIT :
  860.         case SIDL :
  861.             /* Determine why a process should be in a wait state */
  862.             chp = waitingfor( p ) ;
  863.             break ;
  864.         case SRUN :
  865.             chp = "run" ;
  866.             break ;
  867.         case SZOMB :
  868.             chp = "exit" ;
  869.             break ;
  870.         case SSTOP :
  871.             chp = "stop" ;
  872.             break ;
  873.     }
  874.     /* If the process is loaded, list the status information in capitals */
  875.     printf( "%-6.6s ", p->pr_p.p_flag & SLOAD ?
  876.         (capitals( chp, chbuf ), chbuf) : chp ) ;
  877.     /* List process flags */
  878.     printf( "%c%c%c", p->pr_p.p_flag & SSYS ? 'U' :
  879.         p->pr_p.p_flag & STRC ? 'T' : ' ',
  880.         p->pr_p.p_flag & SVFORK ? 'V' :
  881.         p->pr_p.p_flag & SPHYSIO ? 'I' : ' ',
  882.         p->pr_p.p_flag & SUANOM ? 'A' : ' ' ) ;
  883.     /* List process niceness */
  884.     if ( p->pr_p.p_nice != NZERO )          
  885.         printf( "%3d ", p->pr_p.p_nice - NZERO ) ;
  886.     else
  887.         printf( "    " ) ;
  888.     if ( p->pr_p.p_stat == SZOMB )
  889.     {
  890.         prcmd( p, 41, -69 ) ;
  891.         return ;
  892.     }                                       
  893.     /* List process and text virtual sizes */
  894.     printf( "%4d", KBYTES( p->pr_p.p_dsize + p->pr_p.p_ssize ) ) ;
  895.     if ( tp = p->pr_p.p_textp )
  896.         printf( "+%3d ", KBYTES( tp->x_size ) ) ;
  897.     else
  898.         printf( "     " ) ;
  899.     /* List process and text real sizes */
  900.     printf( "%4d", KBYTES( p->pr_p.p_rssize ) ) ;
  901.     if ( tp )
  902.         printf( "+%3d %2.0f ", KBYTES( tp->x_rssize ),
  903.             percentmem( p ) );
  904.     else
  905.         printf( "        " ) ;
  906.     /* List information obtained from the upage. This includes the process
  907.        times and command arguments. */
  908.     if ( !p->pr_upag )
  909.     {
  910.         prcmd( p, 20, -69 ) ;
  911.         return ;
  912.     }                                       
  913.     /* List process time information */
  914. # ifdef BSD42
  915.     time   = Flg.flg_q ? p->pr_rself.ru_utime.tv_sec :
  916.          p->pr_rself.ru_utime.tv_sec + p->pr_rself.ru_stime.tv_sec ;
  917.     utime  = Flg.flg_q ? p->pr_rself.ru_utime.tv_usec :
  918.          p->pr_rself.ru_utime.tv_usec + p->pr_rself.ru_stime.tv_usec ;
  919.     chtime = Flg.flg_q ? p->pr_rchild.ru_utime.tv_sec :
  920.          p->pr_rchild.ru_utime.tv_sec + p->pr_rchild.ru_stime.tv_sec ;
  921.     uchtime = Flg.flg_q ? p->pr_rchild.ru_utime.tv_usec :
  922.          p->pr_rchild.ru_utime.tv_usec + p->pr_rchild.ru_stime.tv_usec ;
  923.     prcpu( time, utime ) ;
  924.     if ( chtime != 0L )
  925.     {
  926.         printf( "+" ) ;
  927.         prcpu( chtime, uchtime ) ;
  928.     }
  929. # else
  930.     time   = Flg.flg_q ? p->pr_vself.vm_utime :
  931.          p->pr_vself.vm_utime + p->pr_vself.vm_stime ;
  932.     chtime = Flg.flg_q ? p->pr_vchild.vm_utime :
  933.          p->pr_vchild.vm_utime + p->pr_vchild.vm_stime ;
  934.     prcpu( time ) ;
  935.     if ( chtime != 0L )
  936.     {
  937.         printf( "+" ) ;
  938.         prcpu( chtime ) ;
  939.     }
  940. # endif
  941.     else
  942.         printf( "      " ) ;
  943. # ifdef BSD42
  944.     if ( time || utime )
  945. # else
  946.     if ( time )
  947. # endif
  948. # ifdef SUN
  949.         printf( " %2.0f ", (double)p->pr_p.p_pctcpu ) ;
  950. # else
  951.         printf( " %2.0f ", p->pr_p.p_pctcpu * 100.0 ) ;
  952. # endif
  953.     else
  954.         printf( "    " ) ;
  955.     /* Finally, list the process command arguments. */
  956.     prcmd( p, 5, -69 ) ;                    
  957. }
  958.  
  959. /* CAPITALS - Converts letters in `chp' to upper-case in buffer `buf'. */
  960. capitals ( chp, buf )
  961.  
  962. register char                   *chp ;
  963. register char                   *buf ;
  964.  
  965. {
  966.     while ( *buf = *chp++ )
  967.     {
  968.         if ( 'a' <= *buf && *buf <= 'z' )
  969.             *buf -= 'a' - 'A' ;
  970.         buf++ ;
  971.     }
  972. }
  973. SHAR_EOF
  974. if test 5844 -ne "`wc -c < 'printproc.c'`"
  975. then
  976.     echo shar: error transmitting "'printproc.c'" '(should have been 5844 characters)'
  977. fi
  978. fi # end of overwriting check
  979. echo shar: extracting "'prsummary.c'" '(632 characters)'
  980. if test -f 'prsummary.c'
  981. then
  982.     echo shar: will not over-write existing file "'prsummary.c'"
  983. else
  984. sed 's/^X//' << \SHAR_EOF > 'prsummary.c'
  985. # include       "sps.h"
  986.  
  987. /* PRSUMMARY - Print the summarising information */
  988. prsummary ()
  989. {
  990.     extern struct summary   Summary ;
  991.  
  992.     printf(
  993. "%D (%Dk) processes, %D (%Dk) busy, %D (%Dk) loaded, %D (%Dk) swapped\n",
  994.         Summary.sm_ntotal, KBYTES( Summary.sm_ktotal ),
  995.         Summary.sm_nbusy, KBYTES( Summary.sm_kbusy ),
  996.         Summary.sm_nloaded, KBYTES( Summary.sm_kloaded ),
  997.         Summary.sm_nswapped, KBYTES( Summary.sm_kswapped ) ) ;
  998.     Summary.sm_ntotal = 0L ;
  999.     Summary.sm_ktotal = 0L ;
  1000.     Summary.sm_nbusy = 0L ;
  1001.     Summary.sm_kbusy = 0L ;
  1002.     Summary.sm_nloaded = 0L ;
  1003.     Summary.sm_kloaded = 0L ;
  1004.     Summary.sm_nswapped = 0L ;
  1005.     Summary.sm_kswapped = 0L ;
  1006. }
  1007. SHAR_EOF
  1008. if test 632 -ne "`wc -c < 'prsummary.c'`"
  1009. then
  1010.     echo shar: error transmitting "'prsummary.c'" '(should have been 632 characters)'
  1011. fi
  1012. fi # end of overwriting check
  1013. echo shar: extracting "'readstatus.c'" '(1170 characters)'
  1014. if test -f 'readstatus.c'
  1015. then
  1016.     echo shar: will not over-write existing file "'readstatus.c'"
  1017. else
  1018. sed 's/^X//' << \SHAR_EOF > 'readstatus.c'
  1019. # include       "sps.h"
  1020. # include       <h/text.h>
  1021.  
  1022. /* READSTATUS - Reads the kernel memory for current processes and texts */
  1023. readstatus ( process, text )
  1024.  
  1025. register struct process         *process ;
  1026. struct text                     *text ;
  1027.  
  1028. {
  1029.     register struct proc    *p ;
  1030.     register struct proc    *p0 ;
  1031.     register struct process *pr ;
  1032.     extern struct info      Info ;
  1033.     extern int              Flkmem ;
  1034.     char                    *getcore() ;
  1035.  
  1036.     /* Read current text information */
  1037.     memseek( Flkmem, (long)Info.i_text0 ) ;
  1038.     if ( read( Flkmem, (char*)text, Info.i_ntext * sizeof( struct text ) )
  1039.     != Info.i_ntext * sizeof( struct text ) )
  1040.         prexit( "sps - Can't read system text table\n" ) ;
  1041.     /* Read current process information */
  1042.     p0 = (struct proc*)getcore( sizeof( struct proc )*Info.i_nproc ) ;
  1043.     memseek( Flkmem, (long)Info.i_proc0 ) ;
  1044.     if ( read( Flkmem, (char*)p0, Info.i_nproc * sizeof( struct proc ) )
  1045.     != Info.i_nproc * sizeof( struct proc ) )
  1046.         prexit( "sps - Can't read system process table\n" ) ;
  1047.     /* Copy process information into our own array */
  1048.     for ( p = p0, pr = process ; pr < &process[ Info.i_nproc ] ; p++, pr++ )
  1049.         pr->pr_p = *p ;
  1050.     free( (char*)p0 ) ;
  1051. }
  1052. SHAR_EOF
  1053. if test 1170 -ne "`wc -c < 'readstatus.c'`"
  1054. then
  1055.     echo shar: error transmitting "'readstatus.c'" '(should have been 1170 characters)'
  1056. fi
  1057. fi # end of overwriting check
  1058. echo shar: extracting "'selectproc.c'" '(1587 characters)'
  1059. if test -f 'selectproc.c'
  1060. then
  1061.     echo shar: will not over-write existing file "'selectproc.c'"
  1062. else
  1063. sed 's/^X//' << \SHAR_EOF > 'selectproc.c'
  1064. # include       "sps.h"
  1065. # include       "flags.h"
  1066.  
  1067. /*
  1068. ** SELECTPROC - Given a process structure, this procedure decides whether
  1069. ** the process is a candidate for printing.
  1070. */
  1071. selectproc ( p, process, thisuid )
  1072.  
  1073. register struct process         *p ;            
  1074. register struct process         *process ;      
  1075. int                             thisuid ;       
  1076.  
  1077. {
  1078.     register union flaglist *fp ;
  1079.     register struct process *pp ;
  1080.     extern struct flags     Flg ;
  1081.  
  1082.     /* Flg.flg_AZ is an internal flag set if one of flags `A' to `Z'
  1083.        was specified. If this is not set, a process is listed only
  1084.        if it or one of its ancestors belongs to the invoking user. */
  1085.     if ( !Flg.flg_AZ )
  1086.         for ( pp = p ; pp > &process[1] ; pp = pp->pr_pptr )
  1087.             if ( thisuid == pp->pr_p.p_uid )
  1088.                 return ( 1 ) ;
  1089.     if ( Flg.flg_A )
  1090.         return ( 1 ) ;
  1091.     if ( Flg.flg_P )
  1092.         for ( fp = Flg.flg_Plist ; fp->f_pid >= 0 ; fp++ )
  1093.             if ( fp->f_pid == p->pr_p.p_pid )
  1094.                 return ( 1 ) ;
  1095.     if ( Flg.flg_U )
  1096.         for ( pp = p ; pp > &process[1] ; pp = pp->pr_pptr )
  1097.             for ( fp = Flg.flg_Ulist ; fp->f_uid >= 0 ; fp++ )
  1098.                 if ( fp->f_uid == pp->pr_p.p_uid )
  1099.                     return ( 1 ) ;
  1100.     switch ( p->pr_p.p_stat )
  1101.     {
  1102.         case SRUN :
  1103.             if ( Flg.flg_B )
  1104.                 return ( 1 ) ;
  1105.             break ;
  1106.         case SSLEEP :
  1107.             if ( Flg.flg_B
  1108.             &&   p->pr_p.p_pri < PZERO && p->pr_p.p_pid > MSPID )
  1109.                 return ( 1 ) ;
  1110.         case SWAIT :
  1111.         case SIDL :
  1112.             if ( Flg.flg_W )
  1113.                 return ( 1 ) ;
  1114.             break ;
  1115.         case SSTOP :
  1116.             if ( Flg.flg_S )
  1117.                 return ( 1 ) ;
  1118.             break ;
  1119.         case SZOMB :
  1120.             if ( Flg.flg_Z )
  1121.                 return ( 1 ) ;
  1122.             break ;
  1123.         default :
  1124.             break ;
  1125.     }
  1126.     return ( 0 ) ;
  1127. }
  1128. SHAR_EOF
  1129. if test 1587 -ne "`wc -c < 'selectproc.c'`"
  1130. then
  1131.     echo shar: error transmitting "'selectproc.c'" '(should have been 1587 characters)'
  1132. fi
  1133. fi # end of overwriting check
  1134. echo shar: extracting "'selecttty.c'" '(368 characters)'
  1135. if test -f 'selecttty.c'
  1136. then
  1137.     echo shar: will not over-write existing file "'selecttty.c'"
  1138. else
  1139. sed 's/^X//' << \SHAR_EOF > 'selecttty.c'
  1140. # include       "sps.h"
  1141. # include       "flags.h"
  1142.  
  1143. /* SELECTTTY - Decides whether this process is interesting for its tty */
  1144. selecttty ( p )
  1145.  
  1146. register struct process         *p ;
  1147.  
  1148. {
  1149.     register union flaglist *fp ;
  1150.     extern struct flags     Flg ;
  1151.  
  1152.     for ( fp = Flg.flg_Tlist ; fp->f_ttyline ; fp++ )
  1153.         if ( fp->f_ttyline == p->pr_tty )
  1154.             return ( 1 ) ;
  1155.     return ( 0 ) ;
  1156. }
  1157. SHAR_EOF
  1158. if test 368 -ne "`wc -c < 'selecttty.c'`"
  1159. then
  1160.     echo shar: error transmitting "'selecttty.c'" '(should have been 368 characters)'
  1161. fi
  1162. fi # end of overwriting check
  1163. echo shar: extracting "'sps.h'" '(6468 characters)'
  1164. if test -f 'sps.h'
  1165. then
  1166.     echo shar: will not over-write existing file "'sps.h'"
  1167. else
  1168. sed 's/^X//' << \SHAR_EOF > 'sps.h'
  1169. # include       <h/param.h>
  1170. # include       <h/dir.h>
  1171. # include       <h/user.h>
  1172. # include       <h/proc.h>
  1173.  
  1174. /*
  1175. ** Maximum # of users to be considered. (Should probably be
  1176. ** approximately double the # of users in /etc/passwd.)
  1177. */
  1178. # define        MAXUSERID       100
  1179. /* Maximum # ttys to be considered ... */
  1180. # define        MAXTTYS         60
  1181. /* Maximum user name length ... */
  1182. # define        UNAMELEN        8
  1183. /* Maximum process-id not to be considered busy ... */
  1184. # define        MSPID           2
  1185. /* # of wait states defined in the `struct info' ... */
  1186. # define        NWAITSTATE      36
  1187.  
  1188. /* Convert clicks to kbytes ... */
  1189. # ifdef SUN
  1190. # define        KBYTES( size )  ((size) << 1)
  1191. # else
  1192. # define        KBYTES( size )  ((size) >> (10 - PGSHIFT))
  1193. # endif
  1194.  
  1195. /* Standard files to be examined ... */
  1196. # define        FILE_MEM        "/dev/mem"      /* System physical memory */
  1197. # define        FILE_KMEM       "/dev/kmem"     /* Kernel virtual memory */
  1198. # define        FILE_SWAP       "/dev/drum"     /* Swap/paging device */
  1199. # define        FILE_DEV        "/dev"          /* Directory of tty entries */
  1200. # define        FILE_SYMBOL     "/vmunix"       /* Symbol file for nlist() */
  1201. # define        FILE_INFO       "/etc/spsinfo"  /* Sps information file */
  1202.  
  1203. /* Structure to hold necessary information concerning a tty ... */
  1204. struct ttyline
  1205. {
  1206.     struct tty              *l_addr ;       /* Ptr to tty struct in kmem */
  1207.     unsigned short          l_pgrp ;        /* Tty process group */
  1208.     char                    l_name[2] ;     /* Tty character name */
  1209.     dev_t                   l_dev ;         /* Tty device # */
  1210. } ;
  1211.  
  1212. /* Structure holding a single hash table entry ... */
  1213. struct hashtab
  1214. {
  1215.     unsigned short          h_uid ;         /* Uid of user entry */
  1216.     char                    h_uname[ UNAMELEN ] ; /* Corresponding name */
  1217. } ;
  1218.  
  1219. /*
  1220. ** Format of the standard information file maintained by sps.
  1221. ** This structure is filled in at initialisation time and then is read back
  1222. ** in whenever sps is invoked.
  1223. ** Note that the pointer variables in this structure refer to
  1224. ** kernel virtual addresses, not addresses within sps.
  1225. ** These variable are typed as such so that pointer arithmetic
  1226. ** on the kernel addresses will work correctly.
  1227. */
  1228. struct info
  1229. {       /* Kernel values determining process, tty and upage info ... */
  1230.     struct proc             *i_proc0 ;      /* address of process table */
  1231.     int                     i_nproc ;       /* length of process table */
  1232.     struct text             *i_text0 ;      /* address of text table */
  1233.     int                     i_ntext ;       /* length of text table */
  1234.     struct inode            *i_inode0 ;     /* address of inode table */
  1235.     int                     i_ninode ;      /* length of inode table */
  1236.     struct buf              *i_swbuf0 ;     /* address of swap buffers */
  1237.     int                     i_nswbuf ;      /* # swap buffers */
  1238.     struct buf              *i_buf0 ;       /* address of i/o buffers */
  1239.     int                     i_nbuf ;        /* # i/o buffers */
  1240.     int                     i_ecmx ;        /* max physical memory address*/
  1241.     struct pte              *i_usrptmap ;   /* page table map */
  1242.     struct pte              *i_usrpt ;      /* page table map */
  1243.     struct cdevsw           *i_cdevsw ;     /* device switch to find ttys */
  1244. # ifdef BSD42
  1245.     struct quota            *i_quota0 ;     /* disc quota structures */
  1246.     int                     i_nquota ;      /* # quota structures */
  1247.     int                     i_dmmin ;       /* The start of the disc map */
  1248.     int                     i_dmmax ;       /* The end of the disc map */
  1249.     struct mbuf             *i_mbutl ;      /* Start of mbuf area */
  1250. # else
  1251.     int                     i_hz ;          /* Clock rate */
  1252. # endif
  1253. # ifdef CHAOS
  1254.     caddr_t                 i_Chconntab ;   /* Chaos connection table */
  1255. # endif
  1256.     /* Kernel addresses are associated with process wait states ... */
  1257.     caddr_t                 i_waitstate[ NWAITSTATE ] ;
  1258.     /* User names, stored in a hash table ... */
  1259.     struct hashtab          i_hnames[ MAXUSERID ] ;
  1260.     /* Tty device info ... */
  1261.     struct ttyline          i_ttyline[ MAXTTYS ] ;
  1262. } ;
  1263.  
  1264. /*
  1265. ** The symbol structure cross-references values read from the kernel with
  1266. ** their place in the info structure, and if such a value is associated with
  1267. ** a process wait state or not.
  1268. */
  1269. struct symbol
  1270. {
  1271.     char                    *s_kname ;      /* Kernel symbol name */
  1272.     char                    s_indirect ;    /* Value requires indirection */
  1273.     caddr_t                 *s_info ;       /* Corresponding info address */
  1274.     char                    *s_wait ;       /* Reason for wait, if any */
  1275. } ;
  1276.  
  1277. /* The `user' structure obtained from /dev/mem or /dev/swap ... */
  1278. union userstate
  1279. {
  1280.     struct user             u_us ;
  1281.     char                    u_pg[ UPAGES ][ NBPG ] ;
  1282. } ;
  1283.  
  1284. /* Information concerning each process filled from /dev/kmem ... */
  1285. struct process
  1286. {
  1287.     struct proc             pr_p ;          /* struct proc from /dev/kmem */
  1288.     struct process          *pr_plink ;     /* Normalised ptrs from above */
  1289.     struct process          *pr_sibling ;   /* Ptr to sibling process */
  1290.     struct process          *pr_child ;     /* Ptr to child process */
  1291.     struct process          *pr_pptr ;      /* Ptr to parent process */
  1292. # ifdef BSD42
  1293.     struct rusage           pr_rself ;      /* Read from upage for self */
  1294.     struct rusage           pr_rchild ;     /* ... and the children */
  1295. # else
  1296.     struct vtimes           pr_vself ;      /* Read from upage for self */
  1297.     struct vtimes           pr_vchild ;     /* ... and the children */
  1298. # endif
  1299.     int                     pr_files ;      /* # open files */
  1300.     struct ttyline          *pr_tty ;       /* Associated tty information */
  1301.     char                    *pr_cmd ;       /* Command args, from upage */
  1302.     int                     pr_upag:1 ;     /* Upage was obtained */
  1303.     int                     pr_csaved:1 ;   /* Cmd args saved by malloc() */
  1304. } ;
  1305.  
  1306. /* Structure to hold summarising information ... */
  1307. struct summary
  1308. {
  1309.     long                    sm_ntotal ;     /* Total # processes */
  1310.     long                    sm_ktotal ;     /* Total virtual memory */
  1311.     long                    sm_nbusy ;      /* # busy processes */
  1312.     long                    sm_kbusy ;      /* Busy virtual memory */
  1313.     long                    sm_nloaded ;    /* # loaded processes */
  1314.     long                    sm_kloaded ;    /* Active resident memory */
  1315.     long                    sm_nswapped ;   /* # swapped processes */
  1316.     long                    sm_kswapped ;   /* Size totally swapped out */
  1317. } ;
  1318. SHAR_EOF
  1319. if test 6468 -ne "`wc -c < 'sps.h'`"
  1320. then
  1321.     echo shar: error transmitting "'sps.h'" '(should have been 6468 characters)'
  1322. fi
  1323. fi # end of overwriting check
  1324. echo shar: extracting "'termwidth.c'" '(490 characters)'
  1325. if test -f 'termwidth.c'
  1326. then
  1327.     echo shar: will not over-write existing file "'termwidth.c'"
  1328. else
  1329. sed 's/^X//' << \SHAR_EOF > 'termwidth.c'
  1330. /*
  1331. ** TERMWIDTH - Sets the external variable `Termwidth' to the # of columns
  1332. ** on the terminal.
  1333. */
  1334. termwidth ()
  1335. {
  1336.     register char           *termtype ;
  1337.     register int            twidth ;
  1338.     char                    buf[ 1025 ] ;
  1339.     extern unsigned         Termwidth ;
  1340.     char                    *getenv() ;
  1341.  
  1342.     Termwidth = 80 ;
  1343.     if ( !(termtype = getenv( "TERM" )) )
  1344.         return ;
  1345.     if ( tgetent( buf, termtype ) != 1 )
  1346.         return ;
  1347.     twidth = tgetnum( "co" ) ;
  1348.     if ( twidth > 40 )
  1349.         Termwidth = twidth ;
  1350. }
  1351. SHAR_EOF
  1352. if test 490 -ne "`wc -c < 'termwidth.c'`"
  1353. then
  1354.     echo shar: error transmitting "'termwidth.c'" '(should have been 490 characters)'
  1355. fi
  1356. fi # end of overwriting check
  1357. echo shar: extracting "'ttystatus.c'" '(2883 characters)'
  1358. if test -f 'ttystatus.c'
  1359. then
  1360.     echo shar: will not over-write existing file "'ttystatus.c'"
  1361. else
  1362. sed 's/^X//' << \SHAR_EOF > 'ttystatus.c'
  1363. # include       "sps.h"
  1364. # include       "flags.h"
  1365. # include       <stdio.h>
  1366. # include       <h/tty.h>
  1367. # ifdef CHAOS
  1368. # include       <chunix/chsys.h>
  1369. # include       <chaos/chaos.h>
  1370. # endif
  1371.  
  1372. /*
  1373. ** TTYSTATUS - Reads the kernel memory for tty structures of active processes.
  1374. ** The addresses of the associated struct ttys of /dev/kmem are kept in the
  1375. ** info structure. Here we use those addresses to access the structures.
  1376. ** Actually, we are mostly interested just in the process group of each tty.
  1377. */
  1378. ttystatus ()
  1379. {
  1380.     register struct ttyline *lp ;
  1381.     struct tty              tty ;
  1382.     extern struct flags     Flg ;
  1383.     extern struct info      Info ;
  1384.     extern int              Flkmem ;
  1385.  
  1386.     if ( Flg.flg_y )
  1387.         printf( "Ty   Dev       Addr Rawq Canq Outq  Pgrp\n" ) ;
  1388.     lp = Info.i_ttyline ;
  1389. # ifdef CHAOS
  1390.     while ( lp->l_name[0] && lp->l_name[0] != 'C' )
  1391. # else
  1392.     while ( lp->l_name[0] )
  1393. # endif
  1394.     {
  1395.         memseek( Flkmem, (long)lp->l_addr ) ;
  1396.         if ( read( Flkmem, (char*)&tty, sizeof( struct tty ) )
  1397.         != sizeof( struct tty ) )
  1398.         {
  1399.             fprintf( stderr,
  1400.                 "sps - Can't read struct tty for tty%.2s\n",
  1401.                 lp->l_name ) ;
  1402.             lp->l_pgrp = 0 ;
  1403.             lp++ ;
  1404.             continue ;
  1405.         }
  1406.         lp->l_pgrp = tty.t_pgrp ;
  1407.         prtty( lp, &tty ) ;
  1408.         lp++ ;
  1409.     }
  1410. # ifdef CHAOS
  1411.     chaosttys( lp ) ;               
  1412. # endif
  1413. }
  1414.  
  1415. /* PRTTY - Print out the tty structure */
  1416. prtty ( lp, tty )
  1417.  
  1418. register struct ttyline         *lp ;
  1419. register struct tty             *tty ;
  1420.  
  1421. {
  1422.     extern struct flags     Flg ;
  1423.  
  1424.     if ( !Flg.flg_y )
  1425.         return ;
  1426.     printf( "%-2.2s %2d,%2d 0x%08x %4d %4d %4d %5d\n",
  1427.         lp->l_name,
  1428.         major( lp->l_dev ),
  1429.         minor( lp->l_dev ),
  1430.         lp->l_addr,
  1431.         tty->t_rawq.c_cc,
  1432.         tty->t_canq.c_cc,
  1433.         tty->t_outq.c_cc,
  1434.         tty->t_pgrp ) ;
  1435. }
  1436.  
  1437. # ifdef CHAOS
  1438.  
  1439. /* CHAOSTTYS - Finds ttys attached to the Chaos net */
  1440. chaosttys ( lp )
  1441.  
  1442. register struct ttyline         *lp ;
  1443.  
  1444. {
  1445.     register struct connection      **cnp ;
  1446.     register int                    i ;
  1447.     struct tty                      tty ;
  1448.     struct connection               *conntab[CHNCONNS] ;
  1449.     struct connection               conn ;
  1450.     extern struct info              Info ;
  1451.     extern int                      Flkmem ;
  1452.  
  1453.     memseek( Flkmem, (long)Info.i_Chconntab ) ;
  1454.     (void)read( Flkmem, (char*)conntab, sizeof( conntab ) ) ;
  1455.     for ( i = 0, cnp = conntab ; cnp < &conntab[CHNCONNS] ; i++, cnp++ )
  1456.     {
  1457.         if ( !*cnp )
  1458.             continue ;
  1459.         memseek( Flkmem, (long)*cnp ) ;
  1460.         (void)read( Flkmem, (char*)&conn, sizeof( struct connection ) );
  1461.         if ( !(conn.cn_flags & CHTTY) )
  1462.             continue ;
  1463.         memseek( Flkmem, (long)conn.cn_ttyp ) ;
  1464.         (void)read( Flkmem, (char*)&tty, sizeof( struct tty ) ) ;
  1465.         if ( lp >= &Info.i_ttyline[MAXTTYS] )
  1466.             prexit( "sps - Too many chaos ttys\n" ) ;
  1467.         lp->l_addr = conn.cn_ttyp ;
  1468.         lp->l_pgrp = tty.t_pgrp ;
  1469.         lp->l_dev = tty.t_dev ;
  1470.         lp->l_name[0] = 'C' ;
  1471.         lp->l_name[1] = i < 10 ? '0'+i : i-10 <= 'z'-'a' ? i-10+'a' :
  1472.                 i-10-('z'-'a')+'A' ;
  1473.         prtty( lp, &tty ) ;
  1474.         lp++ ;
  1475.     }
  1476. }
  1477.  
  1478. # endif
  1479. SHAR_EOF
  1480. if test 2883 -ne "`wc -c < 'ttystatus.c'`"
  1481. then
  1482.     echo shar: error transmitting "'ttystatus.c'" '(should have been 2883 characters)'
  1483. fi
  1484. fi # end of overwriting check
  1485. echo shar: extracting "'waitingfor.c'" '(5822 characters)'
  1486. if test -f 'waitingfor.c'
  1487. then
  1488.     echo shar: will not over-write existing file "'waitingfor.c'"
  1489. else
  1490. sed 's/^X//' << \SHAR_EOF > 'waitingfor.c'
  1491. # include       "sps.h"
  1492. # include       <h/tty.h>
  1493. # include       <h/text.h>
  1494. # ifdef SUN
  1495. # include       <h/vnode.h>
  1496. # include       <ufs/inode.h>
  1497. # else
  1498. # include       <h/inode.h>
  1499. # endif
  1500. # include       <h/buf.h>
  1501. # ifdef BSD42
  1502. # include       <h/quota.h>
  1503. # include       <h/mbuf.h>
  1504. # include       <h/socket.h>
  1505. # include       <h/socketvar.h>
  1506. # endif
  1507.  
  1508. /* 1 if `w' is in the address range defined by `a1' and `a2' ... */
  1509. # define        INRANGE( w, a1, a2 ) \
  1510.             ( (caddr_t)(a1) <= (w) && (w) < (caddr_t)(a2) )
  1511.  
  1512. /* WAITINGFOR - Determine what a process is waiting for and describe it. */
  1513. char    *waitingfor ( p )
  1514.  
  1515. struct process                  *p ;
  1516.  
  1517. {
  1518.     register caddr_t        w ;
  1519.     register struct ttyline *lp ;
  1520.     register struct symbol  *s ;
  1521.     register char           *cp ;
  1522. # ifdef BSD42
  1523.     struct socket           sc ;
  1524. # endif
  1525.     static char             wbuf[ 8 ] ;
  1526.     extern struct info      Info ;
  1527.     extern struct symbol    Symbollist[] ;
  1528.     char                    *sprintf() ;
  1529.  
  1530.     w = p->pr_p.p_wchan ;
  1531.     if ( !w )
  1532.         return ( "null" ) ;
  1533.     /* Waiting for a child process, alternatively in a vfork() ? */
  1534.     if ( INRANGE( w, Info.i_proc0, &Info.i_proc0[ Info.i_nproc ] ) )
  1535.         return ( p->pr_p.p_flag & SNOVM ? "vfork" : "child" ) ;
  1536.     /* Waiting for a page to be brought in ? */
  1537.     if ( INRANGE( w, Info.i_swbuf0, &Info.i_swbuf0[ Info.i_nswbuf ] ) )
  1538.         return ( "swap" ) ;
  1539.     /* Waiting for discio through a block device to complete ? */
  1540.     if ( INRANGE( w, Info.i_buf0, &Info.i_buf0[ Info.i_nbuf ] ) )
  1541.         /* SHOULD ACTUALLY READ AS "blkio" BUT "discio" IS WHAT
  1542.            IS GENERALLY MEANT HERE. */
  1543.         return ( "discio" ) ;
  1544.     /* Waiting for a text page to be brought in ? */
  1545.     if ( INRANGE( w, Info.i_text0, &Info.i_text0[ Info.i_ntext ] ) )
  1546.         return ( "swtext" ) ;
  1547. # ifdef BSD42
  1548.     /* Waiting for an event associated with the quota system ? */
  1549.     if ( INRANGE( w, Info.i_quota0, &Info.i_quota0[ Info.i_nquota ] ) )
  1550.         return ( "quota" ) ;
  1551. # endif
  1552.     /* Waiting for tty I/O ? If so, find which tty it is */
  1553.     for ( lp = Info.i_ttyline ; lp->l_name[0] ; lp++ )
  1554.         if ( INRANGE( w, &lp->l_addr[0], &lp->l_addr[1] ) )
  1555.         {
  1556.             switch ( w - (int)lp->l_addr )
  1557.             {
  1558.                 case (int)&((struct tty*)0)->t_rawq :
  1559.                     /* Read from a tty or slave pty */
  1560.                     cp = "rtty??" ;
  1561.                     break ;
  1562.                 case (int)&((struct tty*)0)->t_outq :
  1563.                     /* Write to a tty or slave pty */
  1564.                     cp = "wtty??" ;
  1565.                     break ;
  1566.                 case (int)&((struct tty*)0)->t_state :
  1567.                     /* Tty not open */
  1568.                     cp = "otty??" ;
  1569.                     break ;
  1570.                 case (int)&((struct tty*)0)->t_outq.c_cf :
  1571.                     /* Read from a controller pty */
  1572.                     cp = "rpty??" ;
  1573.                     break ;
  1574.                 case (int)&((struct tty*)0)->t_rawq.c_cf :
  1575.                     /* Write to a controller pty */
  1576.                     cp = "wpty??" ;
  1577.                     break ;
  1578.                 default :
  1579.                     cp = "?tty??" ;
  1580.                     break ;
  1581.             }
  1582.             cp[4] = lp->l_name[0] ;
  1583.             cp[5] = lp->l_name[1] ;
  1584.             return ( cp ) ;
  1585.         }
  1586.     /* Waiting for an inode ? */
  1587.     if ( INRANGE( w, Info.i_inode0, &Info.i_inode0[ Info.i_ninode ] ) )
  1588.         switch ( ((int)w - (int)Info.i_inode0) % sizeof( struct inode ))
  1589.         {
  1590. # ifdef BSD42
  1591. # ifndef SUN
  1592.             case (int)&((struct inode*)0)->i_exlockc :
  1593.                 /* Exclusive lock on this inode */
  1594.                 return ( "exlock" ) ;
  1595.             case (int)&((struct inode*)0)->i_shlockc :
  1596.                 /* Shared lock on this inode */
  1597.                 return ( "shlock" ) ;
  1598. # endif
  1599. # else
  1600.             case 1 :
  1601.                 return ( "wpipe" ) ;
  1602.             case 2 :
  1603.                 return ( "rpipe" ) ;
  1604.             case (int)&((struct inode*)0)->i_un.i_group.g_datq :
  1605.                 return ( "rmux" ) ;
  1606. # endif
  1607.             default :
  1608.                 /* Inode probably locked */
  1609.                 return ( "inode" ) ;
  1610.         }
  1611. # ifdef BSD42
  1612.     /* Waiting for a structure inside an mbuf ? If so, try to find why */
  1613.     if ( INRANGE( w, Info.i_mbutl,
  1614.     &Info.i_mbutl[ NMBCLUSTERS * CLBYTES / sizeof( struct mbuf ) ] ) )
  1615.         switch ( ((int)w - (int)Info.i_mbutl) % sizeof( struct mbuf )
  1616.             - (int)&((struct mbuf*)0)->m_dat[0] )
  1617.         {
  1618.             case (int)&((struct socket*)0)->so_timeo :
  1619.                 /* Socket timeout event */
  1620.                 return ( "socket" ) ;
  1621.             case (int)&((struct socket*)0)->so_rcv.sb_cc :
  1622.                 /* Read from an empty socket. Here we actually
  1623.                    attempt to determine whether the socket
  1624.                    structure in question really does refer to
  1625.                    a socket, or whether it is in fact a pipe
  1626.                    in disguise. */
  1627.                 return ( getsocket( (struct socket*)(w
  1628.                     - (int)&((struct socket*)0)->so_rcv.sb_cc),
  1629.                         &sc )
  1630.                     && sc.so_type == SOCK_STREAM
  1631.                     && !sc.so_rcv.sb_hiwat
  1632.                     && !sc.so_rcv.sb_mbmax
  1633.                     && (sc.so_state
  1634.                         & (SS_ISCONNECTED|SS_CANTRCVMORE))
  1635.                     ? "rpipe" : "rsockt" ) ;
  1636.             case (int)&((struct socket*)0)->so_snd.sb_cc :
  1637.                 /* Write to a full socket. Again, we try
  1638.                    to determine whether or not this is a
  1639.                    real socket or a pipe. */
  1640.                 return ( getsocket( (struct socket*)(w
  1641.                     - (int)&((struct socket*)0)->so_snd.sb_cc),
  1642.                         &sc )
  1643.                     && sc.so_type == SOCK_STREAM
  1644.                     && sc.so_rcv.sb_hiwat == 2048
  1645.                     && sc.so_rcv.sb_mbmax == 4096
  1646.                     && (sc.so_state
  1647.                         & (SS_ISCONNECTED|SS_CANTSENDMORE))
  1648.                     ? "wpipe" : "wsockt" ) ;
  1649.             default :
  1650.                 /* Other mbuf event */
  1651.                 return ( "mbuf" ) ;
  1652.         }
  1653. # endif
  1654.     /* Look in the symbol table for known wait addresses. */
  1655.     for ( s = Symbollist ; s->s_kname ; s++ )
  1656.         if ( s->s_wait && w == *s->s_info )
  1657.             return ( s->s_wait ) ;  
  1658.     /* No reason for the wait state has been found.
  1659.        Return the wait channel as a hexadecimal address. */
  1660. # ifdef SUN
  1661.     (void)sprintf( wbuf, "x%05x", w ) ;
  1662. # else
  1663.     (void)sprintf( wbuf, "x%05x", w - 0x80000000 ) ;
  1664. # endif
  1665.     return ( wbuf ) ;
  1666. }
  1667.  
  1668. # ifdef BSD42
  1669. /*
  1670. ** GETSOCKET - Reads a `struct socket' from the kernel virtual memory address
  1671. ** identified by `ks' into the buffer `s'.
  1672. */
  1673. getsocket ( ks, s )
  1674.  
  1675. struct socket                   *ks ;
  1676. struct socket                   *s ;
  1677.  
  1678. {
  1679.     extern int              Flkmem ;
  1680.  
  1681.     memseek( Flkmem, (long)ks ) ;
  1682.     return ( read( Flkmem, (char*)s, sizeof( struct socket ) )
  1683.         == sizeof( struct socket ) ) ;
  1684. }
  1685. # endif
  1686. SHAR_EOF
  1687. if test 5822 -ne "`wc -c < 'waitingfor.c'`"
  1688. then
  1689.     echo shar: error transmitting "'waitingfor.c'" '(should have been 5822 characters)'
  1690. fi
  1691. fi # end of overwriting check
  1692. #    End of shell archive
  1693. exit 0
  1694.